/** \file chatgpt.c 
 *  \brief chatgpt
 */
#include <assert.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <string>

#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>

#include "rk_mpi_amix.h"
#include "speechnls.h" 

#include "het_ringbuf.h" 
#include "het_chatgpt.h"  // <-- 唯一必须包含的头文件


#define MAX_ARGS 10
#define CHATGPT_CMD_LINE_LEN 1600
#define CHATGPT_CLI_SOCKET_PATH "/tmp/rk_cmd_socket"
static char *respStr=NULL;// !!!变量只能使用分配的内存，在写wocket后会释放掉

struct  person_info g_personInfo;
/**
 * @brief 获取音频数据
 * @param filename 音频参数
 * @param size 音频数据大小指针
 * @return 成功返回地址，失败返回空
 */
uint8_t * readFile(const char *filename , size_t  *size){
	uint8_t * AudioData = NULL;
	if(size == NULL)
		return NULL;
	FILE *fp = fopen(filename, "rb");
	
	if (fp == NULL) {
		HET_LOGE("Failed to open file %s\n", filename);
		return NULL;
	}
	// 获取文件大小
	fseek(fp, 0, SEEK_END);
	long file_readSize = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	// 分配内存并读取所有数据
	AudioData = (RK_U8 *)malloc(file_readSize);
	if (AudioData == NULL) {
		HET_LOGE("Memory allocation failed!\r\n");
		fclose(fp);
		return NULL;
	}
	*size = fread(AudioData, 1, file_readSize, fp);
	if (*size != file_readSize) {
		HET_LOGE("Failed to read file data!\r\n");
		free(AudioData);
		fclose(fp);
		return NULL;
	}
	fclose(fp);
	return AudioData;
}


/**
 * @brief 获取音频数据
 * @param filename 音频参数
 * @param size 音频数据大小指针
 * @return 成功返回地址，失败返回空
 */
int fillAudioData(const char *paudioData , size_t  sizeLen){
	int ret;
	int pushLen=0, pushSeek=0;
	HET_LOGD("%s total %d !!!\r\n", __func__, sizeLen);
	while(sizeLen && in_play){
		pushLen = rb_push(&audioPlayBuf, paudioData + pushSeek, sizeLen);
		if(pushLen > 0){
			pushSeek += pushLen;
			sizeLen -= pushLen;
			//HET_LOGD("%s reain %d !!!\r\n", __func__, sizeLen);
		}else if(pushLen == 0){
			//HET_LOGD("%s wait %d !!!\r\n", __func__, pushLen);
			usleep(20000);
		}else{
			HET_LOGD("%s error %d !!!\r\n", __func__, pushLen);
			ret = -1;
			break;
		}
	};
	return 0;
}

static pthread_t getStreamThread = 0,sendStreamThread = 0;


void* mp3_thread_fun(void *arg){
	char *play = (char *)arg;
	HET_LOGI("+++\r\n");
    pthread_mutex_lock(&play_lock);
	if(play)
	{
		HET_LOGI("het_adec_audio\r\n");
		het_adec_audio(play);
	}
    pthread_mutex_unlock(&play_lock);
	HET_LOGI("---\r\n");
	return RK_NULL;
}

/**
 * @brief 播放编码音频文件
 * @param argc 参数个数
 * @param argv 参数列表 start stop filename
 */
int rk_cmd_adec(int argc, char *argv[]){
	int ret =0;
	int sizeLen = 0;
	pthread_t mp3_t_id=0;
	int tryNum = 0;
	HET_LOGI("%s mp3 argc [%d] !!!\r\n", __func__, argc);
	if(argc > 0){
		HET_LOGI("%s mp3 argv[0] [%s] !!!\r\n", __func__, argv[0]);
		if(strncmp(argv[0], "stop", strlen("stop")) == 0){
			in_play  = ao_run = RK_FALSE;
			usleep(100000);
			rb_reset(&audioPlayBuf);
		}else if(strncmp(argv[0], "start", strlen("start")) == 0){
			HET_LOGI("start mp3!!!\r\n");
			if(argc > 1 && argv[1]){
				HET_LOGI("%s start mp3 argv[1] [%s] !!!\r\n", __func__, argv[1]);
				in_play = ao_run = RK_TRUE;
				//ret = het_adec_audio(argv[1]);
				pthread_create(&mp3_t_id, NULL, mp3_thread_fun, argv[1]);
				while(!get_sound_out_stat() && tryNum++ < 100) {
					usleep(10000);
				}
			}else{
				HET_LOGE("start mp3 fail !!!\r\n");
			}
		}
	}
	return ret;
}
static RK_BOOL inRecording = RK_FALSE;
/**
 * @brief 录音保存到文件
 * @param argc 参数个数
 * @param argv 参数列表 start stop filename
 */
int rk_cmd_record(int argc, char *argv[]){
	HET_LOGD("%s record argc [%d] !!!\r\n", __func__, argc);
	if(argc > 0){
		HET_LOGD("%s record argv[0] [%s] !!!\r\n", __func__, argv[0]);
		if(strncmp(argv[0], "get", strlen("get")) == 0){
			if(inRecording){
				respStr = strdup("Recording");
			}
		}else if(strncmp(argv[0], "stop", strlen("stop")) == 0){
			if(inRecording){
				HET_LOGI("record stop!!!\r\n");
				inRecording = RK_FALSE;
				if(g_ctx.ai.saveDataFile){
					free(g_ctx.ai.saveDataFile);
					g_ctx.ai.saveDataFile =  RK_NULL;
				}
				if(g_ctx.ai.dstFilePath){
					free(g_ctx.ai.dstFilePath);
					g_ctx.ai.dstFilePath =  RK_NULL;
				}
				het_ai_apply();
				usleep(100000);
				ai_run --;
			}else{
				HET_LOGI("no recording!!!\r\n");
			}
		}else if(strncmp(argv[0], "start", strlen("start")) == 0){
			if(argc > 2 && argv[1] && argv[2]){
				if(!inRecording){
					HET_LOGI("record start !!!\r\n");
					ai_run ++;
					HET_LOGI("%s record start [%s] [%s]!!!\r\n", __func__, argv[1], argv[2]);
					if(g_ctx.ai.saveDataFile){
						free(g_ctx.ai.saveDataFile);
						g_ctx.ai.saveDataFile =  RK_NULL;
					}
					if(g_ctx.ai.dstFilePath){
						free(g_ctx.ai.dstFilePath);
						g_ctx.ai.dstFilePath =  RK_NULL;
					}
					g_ctx.ai.dstFilePath = strdup(argv[1]);
					g_ctx.ai.saveDataFile = strdup(argv[2]);
					HET_LOGI("%s record apply [%s] [%s]!!!\r\n", __func__, g_ctx.ai.dstFilePath, g_ctx.ai.saveDataFile);
					het_ai_apply();
					inRecording = RK_TRUE;
				}else{
					HET_LOGI("in recording!!!\r\n");
				}
			}else{
				HET_LOGE("record start fail !!!\r\n");
			}
		}
	}
	return 0;
}
struct  AudioPlayStruct {
	char *data;
	size_t size;
	int  loop;
};
void* play_thread_fun(void *arg){
	struct  AudioPlayStruct *play = (struct  AudioPlayStruct *)arg;
	HET_LOGD("%s size [%d] loop %d!!!\r\n", __func__, play->size, play->loop);
    pthread_mutex_lock(&play_lock);
	if(play && play->data){
		if(play->loop > 0){
			while(play->loop && in_play){
				if(fillAudioData(play->data,play->size) < 0){
					HET_LOGE("%s fill faile !!!\r\n", __func__);
				}
				play->loop --;
			}
		}else{
			HET_LOGI("%s in_play %d !!!\r\n", __func__,in_play);
			if(fillAudioData(play->data,play->size) < 0){
				HET_LOGE("%s fill faile !!!\r\n", __func__);
			}
		}
		if(play->data)
			free(play->data);
		if(play)
			free(play);
	}
    pthread_mutex_unlock(&play_lock);
	HET_LOGI("%s finish!!!\r\n", __func__);
	return RK_NULL;
}
/**
 * @brief 播放音频数据
 * @param argc 参数个数
 * @param argv 参数列表 filename
 */
int rk_cmd_play(int argc, char *argv[]){
	int ret =0;
	int sizeLen = 0;
	pthread_t play_t_id=0;
	int loop = 1;
	int tryNum = 0;
	HET_LOGD("%s play argc [%d] !!!\r\n", __func__, argc);
	if(argc > 0){
		HET_LOGD("%s play argv[0] [%s] !!!\r\n", __func__, argv[0]);
		if(strncmp(argv[0], "stat", strlen("stat")) == 0){
			HET_LOGD("%s %s!!!\r\n",in_play?"playing":"stop",get_sound_out_stat()?"on":"off");
			if(get_sound_out_stat()){
				respStr = strdup("Playing");
				HET_LOGD("play loop %s %d!!!\r\n",respStr,g_ctx.ao.s32loopCount);
			}
		}else if(strncmp(argv[0], "stop", strlen("stop")) == 0){
			in_play  = ao_run = RK_FALSE;
			usleep(100000);
			rb_reset(&audioPlayBuf);
		}else if(strncmp(argv[0], "start", strlen("start")) == 0){
			HET_LOGI("start play!!!\r\n");
			if(argc > 1 && argv[1]){
				HET_LOGI("%s start play argv[1] [%s] !!!\r\n", __func__, argv[1]);
				if(argc > 2 && argv[2]){
					loop = atoi(argv[2]);
				}
				struct  AudioPlayStruct *play = (struct  AudioPlayStruct *)malloc(sizeof(struct  AudioPlayStruct));
				if(play){
					char * AudioData = readFile(argv[1], (size_t*)&sizeLen);
					if(AudioData){
						play->data = AudioData;
						play->size = sizeLen;
						play->loop = loop;
						in_play = ao_run = RK_TRUE;
						pthread_create(&play_t_id, NULL, play_thread_fun, play);
						while(!get_sound_out_stat() && tryNum++ < 100) {
							usleep(10000);
						}
						HET_LOGI("%s start play %d!!!\r\n", __func__,tryNum);
					}else{
						free(play);
						HET_LOGE("%s start play fail can read file!!!\r\n", __func__);
					}
				}else{
					HET_LOGE("start play fail in malloc!!!\r\n");
				}
			}else{
				HET_LOGE("start play fail arg !!!\r\n");
			}
		}
	}
	return ret;
}
/**
 * @brief 设置双mic模式
 * @param argc 参数个数
 * @param argv 参数列表
 */
int rk_cmd_dualmic(int argc, char *argv[]){
	if(argc > 0 && argv[0] != NULL){
		HET_LOGD("dualmic %s!!!\r\n",argv[0]);
		if(strncmp(argv[0], "on", strlen("on")) == 0){
			if(g_ctx.ai.s32ChnCnt != 2){
				HET_LOGI("dualmic on!!!\r\n");
				ai_run = RK_FALSE;
				usleep(200000);
				g_ctx.ai.s32ChnCnt = 2;
				g_ctx.ai.s32SetTrackMode    = AUDIO_TRACK_NORMAL;
				HET_AI_DestroyChn(&g_ctx.ai);
				usleep(10000);
				HET_AI_CreateChn(&g_ctx.ai);
				het_ai_apply();
				ai_run = RK_TRUE;
			}
		}else if(strncmp(argv[0], "off", strlen("off")) == 0){
			if(g_ctx.ai.s32ChnCnt != 2){
				HET_LOGI("dualmic off!!!\r\n");
				ai_run = RK_FALSE;
				g_ctx.ai.s32ChnCnt = 1;
				g_ctx.ai.s32SetTrackMode    = AUDIO_TRACK_FRONT_LEFT;
				HET_AI_DestroyChn(&g_ctx.ai);
				usleep(10000);
				HET_AI_CreateChn(&g_ctx.ai);
				het_ai_apply();
				ai_run = RK_TRUE;
			}
		}
	}
	return 0;
}
void apply_veq(){
#if 0
	ai_run = 0;
	sleep(1);
	HET_AI_DestroyChn(&g_ctx.ai);
	usleep(10000);
	if(HET_AI_CreateChn(&g_ctx.ai) ==0){
		ai_run = 1;
	}
	#else
	apply_ai_vqe(&g_ctx.ai);
#endif
}
/**
 * @brief 设置增强模式
 * @param argc 参数个数
 * @param argv 参数列表
 */
int rk_cmd_enveq(int argc, char *argv[]){
	if(argc > 0 && argv[0] != NULL){
		HET_LOGD("veq %s!!!\r\n",argv[0]);
		if(strncmp(argv[0], "start", strlen("start")) == 0){
			if(g_ctx.ai.s32ChnCnt == 1){
				if(g_ctx.ai.s32VqeEnable != 1){
					if(g_ctx.ai.s32VqeEnable  != 0){
						RK_MPI_AI_DisableVqe(g_ctx.ai.s32DevId, g_ctx.ai.s32ChnId);
					}
					g_ctx.ai.s32VqeEnable       = 1;
					if(argc > 1 && strncmp(argv[1], "TRACK_LEFT", strlen("TRACK_LEFT"))){
						g_ctx.ai.s32SetTrackMode    = AUDIO_TRACK_FRONT_LEFT;
					}else{
						g_ctx.ai.s32SetTrackMode    = (AUDIO_TRACK_MODE_E)0;
					}
					apply_veq();
				}else{
					HET_LOGI("veq alary start !!!\r\n");
				}
			}else{
				HET_LOGI("dual mic dis veq !!!\r\n");
			}
		}else if(strncmp(argv[0], "customize", strlen("customize")) == 0){
			if(g_ctx.ai.s32ChnCnt == 1){
				if(g_ctx.ai.s32VqeEnable != 2){
					if(g_ctx.ai.s32VqeEnable  != 0){
						RK_MPI_AI_DisableVqe(g_ctx.ai.s32DevId, g_ctx.ai.s32ChnId);
					}
					g_ctx.ai.s32VqeEnable       = 2;
					if(argc > 1 && strncmp(argv[1], "TRACK_LEFT", strlen("TRACK_LEFT"))){
						g_ctx.ai.s32SetTrackMode    = AUDIO_TRACK_FRONT_LEFT;
					}else{
						g_ctx.ai.s32SetTrackMode    = (AUDIO_TRACK_MODE_E)0;
					}
					apply_veq();
				}else{
					HET_LOGI("veq alary start customize!!!\r\n");
				}
			}else{
				HET_LOGI("dual mic dis customize veq !!!\r\n");
			}
		}else if(strncmp(argv[0], "stop", strlen("stop")) == 0){
			if(g_ctx.ai.s32VqeEnable != 0){
				g_ctx.ai.s32VqeEnable       = 0;
				apply_ai_vqe(&g_ctx.ai);
				RK_MPI_AI_SetTrackMode(g_ctx.ai.s32DevId, AUDIO_TRACK_FRONT_LEFT);
			}else{
				HET_LOGI("veq alary stop !!!\r\n");
			}
		}
	}
	return 0;
}

static pthread_t tokenGetconfigThread = 0;
void *token_Getconfig_thread(void *args){
	clifeSmartProductMirrorGetconfig();
	tokenGetconfigThread = 0;
	HET_LOGI("exit token Getconfig thread!!!\r\n");
}
static pthread_t tokenGetTokenThread = 0;
void *token_GetToken_thread(void *args){
	clifeSmartProductMirrorGetconfigStreamGetToken();
	tokenGetTokenThread = 0;
	HET_LOGI("exit token GetToken thread!!!\r\n");
}
static pthread_t tokenCreateSessThread = 0;
void *token_CreateSess_thread(void *args){
	clifeSmartProductMirrorCreateSession();
	tokenCreateSessThread = 0;
	HET_LOGI("exit token CreateSess thread!!!\r\n");
}
/**
 * @brief 设置平台token
 * @param argc 参数个数
 * @param argv 参数列表
 */
int clife_token(int argc, char *argv[]){
	if(argc > 0 && argv[0] != NULL){
		pthread_mutex_lock(&token_lock);
		if(strncmp(argv[0], "stat", strlen("stat")) == 0){
			if(!in_oath){
				respStr = strdup("NoAuth");
			}
		}else if(strncmp(argv[0], "set", strlen("set")) == 0){
			if(argc > 1 && argv[1] != NULL){
				HET_LOGI("key %s!!!\r\n",argv[1]);
				update_clife_config_token(argv[1]);
				if(tokenGetconfigThread == 0){
					HET_LOGI("start token Getconfig thread!!!\r\n");
					pthread_create(&tokenGetconfigThread, NULL, token_Getconfig_thread, NULL);
				}
			}
		}else if(strncmp(argv[0], "session", strlen("session")) == 0){
			HET_LOGI("session!!!\r\n");
			if(tokenGetTokenThread == 0){
				HET_LOGI("start token GetToken thread!!!\r\n");
				pthread_create(&tokenGetTokenThread, NULL, token_GetToken_thread, NULL);
			}
		}else if(strncmp(argv[0], "sessId", strlen("sessId")) == 0){
			if(argc > 1 && argv[1] != NULL){
				HET_LOGI("sessid %s!!!\r\n",argv[1]);
				update_clife_agent_sessionId(argv[1]);
			}
		}else if(strncmp(argv[0], "createSess", strlen("createSess")) == 0){
			HET_LOGI("createSess !!!\r\n");
			if(tokenCreateSessThread == 0){
				HET_LOGI("start token CreateSess thread!!!\r\n");
				pthread_create(&tokenCreateSessThread, NULL, token_CreateSess_thread, NULL);
			}
		}else if(strncmp(argv[0], "getSessId", strlen("getSessId")) == 0){
			if(get_clife_agent_sessionId()){
				HET_LOGI("have session id !!!\r\n");
				respStr = strdup(get_clife_agent_sessionId());
			}else{
				HET_LOGI("haven't session id !!!\r\n");
			}
		}
		pthread_mutex_unlock(&token_lock);
	}
	return 0;
}


static pthread_t ttsThread = 0;
void *tts_thread(void *args){
	char * ttsStr = (char *)args;
	if(ttsStr){
		HET_LOGI("ttsStr %s !!!\r\n",ttsStr);
		clife_agent_clean();
		in_play = ao_run = RK_TRUE;
		HET_LOGI("tts thread exec!!!\r\n");
		//speechSynthesizerPut(ttsStr ,NULL);
		speechSynthesizerPutMp3(ttsStr);
		free(ttsStr);
		HET_LOGI("tts thread exec finish!!!\r\n");
	}else{
		HET_LOGE("tts thread not exec!!!\r\n");
	}
	ttsThread = 0;
}

static pthread_t ttsMp3Thread = 0;
void *tts_mp3_thread(void *args){
	char * ttsStr = (char *)args;
	if(ttsStr){
		HET_LOGI("ttsMp3Str %s !!!\r\n",ttsStr);
		clife_agent_clean();
		in_play = ao_run = RK_TRUE;
		HET_LOGI("tts mp3 thread exec!!!\r\n");
		speechSynthesizerPutMp3(ttsStr);
		free(ttsStr);
		HET_LOGI("tts mp3 thread exec finish!!!\r\n");
	}else{
		HET_LOGE("tts mp3 thread not exec!!!\r\n");
	}
	ttsMp3Thread = 0;
}
/**
 * @brief 调用tts
 * @param argc 参数个数
 * @param argv 参数列表 filename
 */
// 声音转文本 filename
int rk_cmd_tts(int argc, char *argv[]){
	if(argc > 0){
		if(strncmp(argv[0], "stat", strlen("stat")) == 0){
			if(in_tts){
				respStr = strdup("Ttsing");
			}
		}else if(strncmp(argv[0], "start", strlen("start")) == 0){
			HET_LOGI("start tts!!!\r\n");
			if(ttsThread == 0){
				in_tts = in_play = ao_run = RK_TRUE;
				HET_LOGI("start tts thread!!!\r\n");
				pthread_create(&ttsThread, NULL, tts_thread, clife_agent_get());
			}else{
				HET_LOGI("start tts fail!!!\r\n");
			}
			nls_recognizer_clean();
			HET_LOGI("tts thread id %d!!!\r\n",ttsThread);
		}else if(argc > 1 && strncmp(argv[0], "request", strlen("request") ) == 0){
			HET_LOGI("request tts %s!!!\r\n",argv[1]);
			size_t sizeLen = 0;
			char * pText = (char *)readFile(argv[1],&sizeLen);
			if(pText){
				if(ttsThread == 0){
				in_tts = in_play = ao_run = RK_TRUE;
					pthread_create(&ttsThread, NULL, tts_thread, pText);
				}
				//speechSynthesizerPut(pText,(char*)"/userdata/tts.wav");
			}
		}else if(argc > 1 && strncmp(argv[0], "mp3", strlen("mp3") ) == 0){
			HET_LOGI("request mp3 tts %s!!!\r\n",argv[1]);
			size_t sizeLen = 0;
			char * pText = (char *)readFile(argv[1],&sizeLen);
			if(pText){
				if(ttsMp3Thread == 0){
				in_tts = in_play = ao_run = RK_TRUE;
					pthread_create(&ttsMp3Thread, NULL, tts_mp3_thread, pText);
				}
				//speechSynthesizerPut(pText,(char*)"/userdata/tts.wav");
			}
		}
	}
	return 0;
}

static pthread_t asrThread = 0;
void *asr_thread(void *args){
	char * recStr = (char *)args;
	if(recStr){
		HET_LOGI("%s asr thread begin\r\n", __func__);
		speechRecognizerPut(recStr,false);
		HET_LOGI("%s asr thread end\r\n", __func__);
		het_ai_clean_rec();
		HET_LOGI("%s asr thread clean\r\n", __func__);
	}
	in_asr = RK_FALSE;
	asrThread = 0;
}

/**
 * @brief 调用asr
 * @param argc 参数个数
 * @param argv 参数列表 filename
 */
// 文本转声音 filename
int rk_cmd_asr(int argc, char *argv[]){
	HET_LOGD("%s  asr argc [%d] !!!\r\n", __func__, argc);
	if(argc > 0){
		HET_LOGD("%s asr argv[0] [%s] !!!\r\n", __func__, argv[0]);
		if(strncmp(argv[0], "get", strlen("get")) == 0){
			respStr = nls_recognizer_get();
		}else if(strncmp(argv[0], "stat", strlen("stat")) == 0){
			if(in_asr){
				respStr = strdup("Asring");
			}
		}else if(strncmp(argv[0], "clean", strlen("clean")) == 0){
			HET_LOGI("clean asr!!!\r\n");
			if(g_ctx.ai.s32loopCount != -1){
				het_ai_clean_rec();
			}
			nls_recognizer_clean();
		}else if(strncmp(argv[0], "start", strlen("start")) == 0){
			HET_LOGI("start asr!!!\r\n");
			in_play  = ao_run = RK_FALSE;
			if(asrThread == 0){
				in_asr = RK_TRUE;
				pthread_create(&asrThread, NULL, asr_thread, het_ai_has_rec());
			}
		}else if(argc > 1 && strncmp(argv[0], "request", strlen("request") ) == 0){
			HET_LOGI("request asr %s!!!\r\n",argv[1]);
			if(asrThread == 0){
				in_asr = RK_TRUE;
				pthread_create(&asrThread, NULL, asr_thread, argv[1]);
			}
		}
	}
	return 0;
}
/**
 * @brief 调用大模型
 * @param argc 参数个数
 * @param argv 参数列表 filename
 */
// 请求openai apikey token filename
int rk_cmd_openai(int argc, char *argv[]){
	HET_LOGD("%s  openai argc [%d] !!!\r\n", __func__, argc);
	if(argc > 3){
		HET_LOGD("%s openai argv[0] [%s] !!!\r\n", __func__, argv[0]);
		if(strncmp(argv[0], "disable", strlen("disable")) == 0){
			update_chat_cloud(0);
		}else if(strncmp(argv[0], "enable", strlen("enable")) == 0){
			if(strlen(argv[1]) && strlen(argv[2]) && strlen(argv[3])){
				HET_LOGI("enable openai!!!\r\n");
				char * pKey = strdup(argv[1]);
				char * pModel = strdup(argv[2]);
				char * pUrl = strdup(argv[3]);
				update_openai_key(pKey);
				update_openai_model(pModel);
				update_openai_url(pUrl);
				update_chat_cloud(1);
			}else{
				update_chat_cloud(0);
			}
		}
	}
	return 0;
}
static RK_BOOL inChating = RK_FALSE;
RK_BOOL get_chat_stat(){
	return inChating;
}

/**
 * @brief 识别音频
 * @param argc 参数个数
 * @param argv 参数列表 filename
 */
int rk_cmd_chat(int argc, char *argv[]){
	HET_LOGD("%s  chat argc [%d] !!!\r\n", __func__, argc);
	if(argc > 0){
		HET_LOGD("%s chat argv[0] [%s] !!!\r\n", __func__, argv[0]);
		if(strncmp(argv[0], "stream", strlen("stream")) == 0){
			if(!inChating){
				HET_LOGI("stream chat!!!\r\n");
				ai_run ++;
				inChating = RK_TRUE;
				g_ctx.ai.s32RecognizerEnable       = 1;
			}
			if(ai_run == 0){
				ai_run ++;
			}
			g_ctx.ai.s32loopCount       = -1;
		}else if(strncmp(argv[0], "stat", strlen("stat")) == 0){
			if(inChating){
				respStr = strdup("Chating");
			}
			//HET_LOGI("chat loop %d!!!\r\n",g_ctx.ai.s32loopCount);
		}else if(strncmp(argv[0], "get", strlen("get")) == 0){
			HET_LOGD("chat get!!!\r\n");
			char * chatStr = het_ai_has_rec();
			if(chatStr){
				respStr = strdup(chatStr);
				HET_LOGI("chat result %s!!!\r\n",chatStr);
			}
		}else if(strncmp(argv[0], "stop", strlen("stop")) == 0){
			if(inChating){
				inChating = RK_FALSE;
				if(ai_run > 0){
					ai_run --;
				}
				g_ctx.ai.s32RecognizerEnable = 0;
				g_ctx.ai.s32loopCount = 0;
				het_ai_clean_rec();
				nls_recognizer_clean();
			}
		}else if(strncmp(argv[0], "start", strlen("start")) == 0){
			if(!inChating){
				HET_LOGI("start chat!!!\r\n");
				ai_run ++;
				inChating = RK_TRUE;
				in_play  = ao_run = RK_FALSE;
				g_ctx.ai.s32RecognizerEnable = 1;
				het_ai_clean_rec();
			}
			if(ai_run == 0){
				ai_run ++;
			}
			g_ctx.ai.s32loopCount = 1;
		}
	}
	return 0;
}

static pthread_t agentThread = 0;
void *agent_thread(void *args){
	char * recStr = (char *)args;
	if(recStr ){
		HET_LOGI("agent %s !!!\r\n",recStr);
		// 这是用于清除所有数据
		nls_recognizer_clean();
		if(get_chat_cloud()){
			openaiPut(recStr,false);
		}else{
			if(get_clife_agent_sessionId()){
				clifeMicroAppChat(recStr, 0, false);
			}else{
				clifeMicroAppToolChat(recStr,0,false);
			}
		}
	}
	agentThread = 0;
}

/**
 * @brief 获取当前识别 
 * @param argc 参数个数
 * @param argv 参数列表 filename
 */
int rk_cmd_agent(int argc, char *argv[]){
	HET_LOGD("%s  agent argc [%d] !!!\r\n", __func__, argc);
	if(argc > 0){
		HET_LOGD("%s agent argv[0] [%s] !!!\r\n", __func__, argv[0]);
		if(strncmp(argv[0], "get", strlen("get")) == 0){
			if(get_chat_cloud()){
				respStr = nls_openai_get();
			}else{
				respStr = clife_agent_get();
			}
		}else if(strncmp(argv[0], "stat", strlen("stat")) == 0){
			if(in_query){
				respStr = strdup("Querying");
			}
		}else if(strncmp(argv[0], "start", strlen("start")) == 0){
			HET_LOGI("start agent!!!\r\n");
			if(agentThread == 0){
				pthread_create(&agentThread, NULL, agent_thread, nls_recognizer_get());
			}else{
				HET_LOGI("start agent fail!!!\r\n");
			}
		}else if(argc > 1 && strncmp(argv[0], "request", strlen("request") ) == 0){
			HET_LOGD("request agent!!!\r\n");
			if(agentThread == 0){
				pthread_create(&agentThread, NULL, agent_thread, argv[1]);
			}
		}
	}
	return 0;
}
/**
 * @brief 音量
 * @param argc 参数个数
 * @param argv 参数列表 filename
 */
int rk_cmd_volume(int argc, char *argv[]){
	HET_LOGD("%s  volume argc [%d] !!!\r\n", __func__, argc);
	if(argc > 0){
		HET_LOGD("%s volume argv[0] [%s] !!!\r\n", __func__, argv[0]);
		int volume = atoi(argv[0]);
		HET_LOGI("apply volume %d!!!\r\n",volume);
		if(volume >= 0 && volume <= 100){
			//HET_AI_apply_Volume(volume);
			HET_AO_apply_Volume(volume);
		}
	}
	return 0;
}
/**
 * @brief clfie平台配置
 * @param argc 参数个数
 * @param argv 参数列表 
 */
int rk_cmd_clife(int argc, char *argv[]){
	HET_LOGD("%s  clife argc [%d] !!!\r\n", __func__, argc);
	if(argc > 0){
		HET_LOGD("%s agent argv[0] [%s] !!!\r\n", __func__, argv[0]);
		if(strncmp(argv[0], "configUrl", strlen("configUrl")) == 0){
			if(argc > 1 ){
				update_clife_config_url(argv[1]);
			}
		}else if(strncmp(argv[0], "agentUrl", strlen("agentUrl")) == 0){
			if(argc > 1 ){
				update_clife_agent_url(argv[1]);
			}
		}
	}
	return 0;
}
/**
 * @brief 静音
 * @param argc 参数个数
 * @param argv 参数列表 filename
 */
int rk_cmd_mute(int argc, char *argv[]){
	HET_LOGD("%s  mute argc [%d] !!!\r\n", __func__, argc);
	if(argc > 0){
		HET_LOGD("%s mute argv[0] [%s] !!!\r\n", __func__, argv[0]);
		int mute = atoi(argv[0]);
		HET_LOGI("apply mute %d !!!\r\n",mute);
		if(mute == 0 || mute == 1){
			//HET_AI_apply_Mute(mute);
			HET_AO_apply_Mute(mute);
		}
	}
	return 0;
}

/**
 * 查到个人信息的key
 */
struct  person_key *findPersonKey(char * key){
	int i;
	if(key){
		for(i = 0; i < 16; i++){
			if(g_personInfo.keys[i].name && strncmp(g_personInfo.keys[i].name, key, strlen(key)) == 0){
				return &g_personInfo.keys[i];
			}
		}
	}else{
		for(i = 0; i < 16; i++){
			if(g_personInfo.keys[i].name == NULL){
				return &g_personInfo.keys[i];
			}
		}
	}
	return NULL;
}

static pthread_t personDeleteThread = 0;
void *person_delete_thread(void *args){
	update_user_id(NULL);
	clifeSmartProductMirrorDeleteSession(get_clife_agent_sessionId());
	update_clife_agent_sessionId(NULL);
	memset(&g_personInfo, 0, sizeof(g_personInfo));
	personDeleteThread = 0;
}
/**
 * @brief 个人信息
 * @param argc 参数个数
 * @param argv 参数列表 
 */
int rk_cmd_person(int argc, char *argv[]){
	HET_LOGD("%s  person argc [%d] !!!\r\n", __func__, argc);
	if(strncmp(argv[0], "clean", strlen("clean")) == 0){
		HET_LOGI("%s person clean [%s] !!!\r\n", __func__, argv[1]);
		update_user_id(NULL);
		memset(&g_personInfo, 0, sizeof(g_personInfo));
		if(personDeleteThread == 0){
			pthread_create(&personDeleteThread, NULL, person_delete_thread, NULL);
		}
	}else if(argc > 1){
		HET_LOGI("%s person argv[0] [%s] !!!\r\n", __func__, argv[0]);
		if(strncmp(argv[0], "set", strlen("set")) == 0){
			HET_LOGI("%s person set [%s] !!!\r\n", __func__, argv[1]);
			if(strncmp(argv[1], "userId", strlen("userId")) == 0){
				update_user_id(argv[2]);
			}else if(strncmp(argv[1], "sessId", strlen("sessId")) == 0){
				update_clife_agent_sessionId(argv[2]);
			}else{
				if(argc > 2){
					struct  person_key * pKey = findPersonKey(argv[1]);
					if(pKey){
						HET_LOGI("%s person add [%s] !!!\r\n", __func__, pKey->name);
						pKey->value = strdup(argv[2]);
					}else{
						pKey = findPersonKey(NULL);
						if(pKey){
							pKey->name = strdup(argv[1]);
							pKey->value = strdup(argv[2]);
							HET_LOGI("%s person new [%s] [%s]!!!\r\n", __func__, pKey->name, pKey->value);
						}else{
							HET_LOGE("%s person info full %s not save !!!\r\n", __func__, argv[2]);
						}
					}
				}
			}
		} else if(strncmp(argv[0], "del", strlen("del")) == 0){
			HET_LOGI("%s person del [%s] !!!\r\n", __func__, argv[1]);
			if(strncmp(argv[1], "userId", strlen("userId")) == 0){
				update_user_id(NULL);
			}else if(strncmp(argv[1], "sessId", strlen("sessId")) == 0){
				if(personDeleteThread == 0){
					pthread_create(&personDeleteThread, NULL, person_delete_thread, NULL);
				}
			}else{
				struct  person_key * pKey = findPersonKey(argv[1]);
				if(pKey){
					HET_LOGI("%s person del [%s] !!!\r\n", __func__, pKey->name);
					free(pKey->value);
					pKey->value = NULL;
					free(pKey->name);
					pKey->name = NULL;
				}
			}
		}else if(strncmp(argv[0], "get", strlen("get")) == 0){
			HET_LOGI("%s person get [%s] !!!\r\n", __func__, argv[1]);
			if(strncmp(argv[1], "userId", strlen("userId")) == 0){
				if(get_user_id()){
					respStr = strdup(get_user_id());
				}
			}else if(strncmp(argv[1], "sessId", strlen("sessId")) == 0){
				if(get_clife_agent_sessionId()){
					respStr = strdup(get_clife_agent_sessionId());
				}
			}else{
				struct  person_key * pKey = findPersonKey(argv[1]);
				if(pKey){
					HET_LOGI("%s person get [%s] !!!\r\n", __func__, pKey->name);
					respStr = strdup(pKey->value);
				}
			}
		} 
	}
	return 0;
}
static command_t socket_cmd_table[] = {
	{"mp3", "play audio file (mp3/aac)", rk_cmd_adec},// 播放文件  filename
	{"record", "record to wav file", rk_cmd_record},// 录音 start/stop filename
	{"play", "play pcm file data", rk_cmd_play},// 输出音频 filename
	{"tts", "call tts api", rk_cmd_tts},// 文本转声音
	{"asr", "user file call asr api", rk_cmd_asr},// 声音转文字 filename
	{"openai", "setting openai api", rk_cmd_openai},// 请求openai apikey token filename
	{"chat", "chat with chatgpt", rk_cmd_chat},// 识别 filename
	{"token", "clife token", clife_token},// 识别 filename
	{"dualmic", "set dula mic mode", rk_cmd_dualmic},// 双mic模式 
	{"veq", "set one mic mode", rk_cmd_enveq},// 回采模式
	{"agent", "agent request and respon", rk_cmd_agent},// 智能请求和返回
	{"mute", "mute for sound", rk_cmd_mute},// 静音
	{"volume", "volume for sound", rk_cmd_volume},// 音量
	{"clife", "clife config", rk_cmd_clife},// 平台配置
	{"person", "info for person", rk_cmd_person},// 个人信息配置
};

static int rk_tokenize_cmd(char *cmd, char *argv[], int is_at_cmd)
{
	char *pos;
	int argc = 0;
	HET_LOGD("rk_tokenize_cmd %s\r\n", cmd);

	pos = cmd;
	for (;;) {
		while (*pos == ' ')
			pos++;
		if (*pos == '\0')
			break;
		if (*pos == '"') {
			argv[argc] = pos + 1;
			char *pos2 = strrchr(pos, '"');
			if (pos2) {
				*pos2 = '\0';
				pos = pos2 + 1;
			}
		} else {
			argv[argc] = pos;
		}
		argc++;
		if (argc == MAX_ARGS)
			break;
		while (*pos != '\0' && *pos != ' ')
			pos++;
		if (*pos == ' ')
			*pos++ = '\0';
	}

	return argc;
}
#define OKSTR "OK\n"
#define ERRSTR "ERR\n"
static int rk_cmd_parse(char *arg)
{
	int i = 0;
	int cnt = sizeof(socket_cmd_table) / sizeof(socket_cmd_table[0]);
	char *argv[MAX_ARGS];
	int argc;
	int ret = 0;
	HET_LOGD("rk_cmd_parse %s\r\n", arg);

	argc = rk_tokenize_cmd(arg, argv, 0);
	HET_LOGD("[%s %d]: %s %s\r\n", arg, argc, argv[0], argv[1]);
	if (argc) {
		for (i = 0; i < cnt; i++) {
			if (!strcmp(socket_cmd_table[i].cmd, argv[0])) {
				HET_LOGD("exec: %s \r\n", socket_cmd_table[i].cmd);
				ret = socket_cmd_table[i].exec(argc - 1, &argv[1]);
				if (ret == 0) {
					HET_LOGD(OKSTR);
				} else {
					HET_LOGI("FAIL  %d\n", ret);
				}
				break;
			}
		}
	}

	return true;
}

int rk_cmd_cli(int argc, char *argv[])
{
	char command[CHATGPT_CMD_LINE_LEN];
	struct sockaddr_un ser_un;
	int tmp_argc = 1;
	int socket_fd = 0;
	int ret = 0;
	int i = 0;

	memset(command, 0, sizeof(command));
	sprintf(command, "%s", argv[tmp_argc++]);

	while (tmp_argc < argc)
	{
		sprintf(command, "%s %s", command, argv[tmp_argc++]);
	}

	socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (socket_fd <= 0)
	{
		HET_LOGI("open socket err\r\n");
		return -1;
	}

	memset(&ser_un, 0, sizeof(ser_un));
	ser_un.sun_family = AF_UNIX;
	strcpy(ser_un.sun_path, CHATGPT_CLI_SOCKET_PATH);

	ret = connect(socket_fd, (struct sockaddr *)&ser_un, sizeof(struct sockaddr_un));
	if(ret < 0)
	{
		HET_LOGE("connect err\r\n");
		return -1; 
	}
	//HET_LOGD("rkchatgpt cmd: %s\r\n", command);
	write(socket_fd, command, strlen(command)+1);
	command[0]='\0';
	read(socket_fd, command, sizeof(command));
	if (strncmp(command, OKSTR,strlen(OKSTR)))
	{
		HET_LOGE("errror:%s\n", command);
		return -1;
	} else{
		printf("%s\n", command);
	}
	return 0;
}


static int connect_fd = 0;

void *rk_cmd_server_command_func(void *arg)
{
	struct sockaddr_un ser_un;
	int socket_fd = 0;
	int ret = 0;
	char cmd_line[CHATGPT_CMD_LINE_LEN];
	
	// 初始化mpi
	ret = RK_MPI_SYS_Init();

    if(ret!=0){
		HET_LOGE("SYS_Init fail:%d\r\n", ret);
		return	RK_NULL;
	}
	socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (socket_fd <= 0) {
		HET_LOGE("open socket err\r\n");
		return NULL;
	}

	unlink(CHATGPT_CLI_SOCKET_PATH);

	memset(&g_personInfo, 0, sizeof(g_personInfo));
	memset(&ser_un, 0, sizeof(ser_un));
	ser_un.sun_family = AF_UNIX;
	strcpy(ser_un.sun_path, CHATGPT_CLI_SOCKET_PATH);
	ret = bind(socket_fd, (struct sockaddr *)&ser_un, sizeof(struct sockaddr_un));
	if (ret < 0) {
		HET_LOGE("bind err %s %s\r\n", CHATGPT_CLI_SOCKET_PATH, strerror(errno));
		return NULL;
	}

	ret = listen(socket_fd, 5);
	if (ret < 0) {
		HET_LOGE("listen err\n");
		return NULL;
	}

	rkchatgpt_init();
	HET_LOGI("start pthread HET_AI_Get_Stream_Thread!!!\r\n");
	pthread_create(&getStreamThread, NULL, HET_AI_Get_Stream_Thread, (void *)(&g_ctx.ai));
	HET_LOGI("start pthread HET_AO_Play_Stream_Thread!!!\r\n");
	pthread_create(&sendStreamThread, NULL, HET_AO_Play_Stream_Thread, (void *)(&g_ctx.ao));

	while (global_run) {
		HET_LOGD("accept ...\n");
		connect_fd = accept(socket_fd, NULL, NULL);
			if (connect_fd < 0) {
			continue;
		}
		
		HET_LOGD("read ...\n");
		memset(cmd_line, 0, sizeof(cmd_line));
		ret = read(connect_fd, cmd_line, sizeof(cmd_line));
		if (ret <= 0) {
			HET_LOGE("cmd_line error!!!\n");
			write(connect_fd, ERRSTR, strlen(ERRSTR)+1);
		}else{
			
		
			HET_LOGD("cmd_line: %s [%d]\n", cmd_line, strlen(cmd_line));

			if (!strncmp(cmd_line, "quit", strlen("quit"))) {
				global_run = RK_FALSE;
				break;
			}

			rk_cmd_parse(cmd_line);
			//rk_cmd_parse(cmd_line);
			HET_LOGD("write ...\n");
			if(respStr){
				if(strcmp(respStr,"Playing") != 0) {
					HET_LOGI("respStr:%s\n",respStr);
				}
				write(connect_fd, OKSTR, strlen(OKSTR));
				write(connect_fd, respStr, strlen(respStr));
				free(respStr);
				respStr =  NULL;
				write(connect_fd, '\0', 1);
			}else
			{
				write(connect_fd, OKSTR, strlen(OKSTR) + 1);
			}
		}
		
		close(connect_fd);
	}

	close(socket_fd);
	global_run = RK_FALSE;
	if(getStreamThread)
		pthread_join(getStreamThread, NULL);
	if(sendStreamThread)
		pthread_join(sendStreamThread, NULL);
	HET_LOGI("%s RK_MPI_SYS_Exit!\r\n", __func__);
	RK_MPI_SYS_Exit();
	update_openai_clean();
	HET_LOGI("%s quit!\r\n", __func__);
	return NULL;
}
void cmd_exit(){
	if(connect_fd){
		write(connect_fd, "quit", strlen("quit") + 1);
	}
}